#pragma once

#include <stdint.h>
#include <vector>
#include <memory>

namespace rr {
namespace nio {

/// A buffer class modeled after org.jboss.netty.buffer.ChannelBuffer
///
/// @code
/// +-------------------+------------------+------------------+
/// | prependable bytes |  readable bytes  |  writable bytes  |
/// |                   |     (CONTENT)    |                  |
/// +-------------------+------------------+------------------+
/// |                   |                  |                  |
/// 0      <=      readerIndex   <=   writerIndex    <=     size

class Buffer
{
public:
    static const size_t kCheapPrepend = 8;
    static const size_t kInitialSize = 1024;
    static const size_t kMaxSize = 2*1024*1024;

    using Sptr = std::shared_ptr<Buffer>;

    Buffer(int32_t init_size = kInitialSize, int32_t max_size = kMaxSize);

    void Clear();

    size_t	ReadableBytes()		{ return writer_index_ - reader_index_; }
	size_t	WritableBytes()		{ return data_.size() - writer_index_; }
    size_t	PrependableBytes()  { return reader_index_; }
    const char* Peek() const	{ return Begin() + reader_index_; }

//
    void Retrieve(size_t len);
    void RetrieveAll();
//
    bool EnsureWritableBytes(size_t len);
    char* BeginWrite()    { return Begin() + writer_index_; }
    const char* BeginWrite() const   { return Begin() + writer_index_; }
    void HasWritten(size_t len)	{ writer_index_ += len; }
    bool Append(const char* data, size_t len);

private:
    char*	Begin()			  { return &*data_.begin(); }
    const char* Begin() const { return &*data_.begin(); }
    bool MakeSpace(size_t len);

private:
    std::vector<char> data_;
    int32_t max_size_ = 2*1024*1024;
    size_t reader_index_ = 0;
    size_t writer_index_ = 0;
};

} //namespace 
} //namespace 
